package com.ntt.benew.dictionary.view

import android.content.Context
import android.graphics.*
import android.text.TextPaint
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import androidx.core.content.res.ResourcesCompat
import com.ntt.benew.dictionary.R

class SpellCharView(context: Context, attributeSet: AttributeSet? = null) :
    View(context, attributeSet) {
    //背景线
    private var backgroundLinePaint = Paint()

    //背景虚线
    private var backgroundDashPaint = Paint()

    //文本画笔
    private var textPaint = TextPaint()

    //连接线画笔
    private var connectLinePaint = Paint()

    //背景虚线路径
    private var dashPath = Path()

    //连接线路径
    private var connectLinePath = Path()

    //字符开始X坐标
    private var baseLineX = 0f

    //文字高亮颜色
    private var hlTextColor: Int = ResourcesCompat.getColor(resources, R.color.ntt_ffA800, null)

    //文字默认颜色
    private var normalTextColor: Int = Color.BLACK

    //连接线颜色
    private var connectLineColor: Int =
        ResourcesCompat.getColor(resources, R.color.ntt_5cff6d, null)

    //文本大小
    private var textSize = resources.getDimensionPixelSize(R.dimen.x_large_word_size).toFloat()

    //高亮点
    private var hlPositions: List<Int>? = null

    //连接点坐标
    private var connectPositionCoordinate: MutableList<Float> = mutableListOf()

    //连接点位置
    private var connectPositions: List<Int>? = null

    //文本
    private var contentText: String? = null

    //调整文本宽度
    private var resizeWidth = 0


    init {
        val lineColor = ResourcesCompat.getColor(resources, R.color.ntt_999999, null)
        backgroundLinePaint.isAntiAlias = true
        backgroundLinePaint.isDither = true
        backgroundLinePaint.color = lineColor
        backgroundLinePaint.style = Paint.Style.STROKE
        backgroundLinePaint.strokeWidth = 3f

        backgroundDashPaint.isAntiAlias = true
        backgroundDashPaint.isDither = true
        backgroundDashPaint.style = Paint.Style.STROKE
        backgroundDashPaint.pathEffect = DashPathEffect(floatArrayOf(5f, 5f), 0f)
        backgroundDashPaint.color = lineColor
        backgroundDashPaint.strokeWidth = 0.5f


        textPaint.color = normalTextColor
        textPaint.isDither = true
        textPaint.textSize = textSize
        textPaint.isAntiAlias = true

        connectLinePaint.color = connectLineColor
        connectLinePaint.isAntiAlias = true
        connectLinePaint.isDither = true
        connectLinePaint.style = Paint.Style.STROKE
        connectLinePaint.strokeWidth = 2f
    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawBackRectView(canvas)
        drawTextView(canvas)
        drawConnectLineView(canvas)
    }

    /**
     * 绘制背景线
     */
    private fun drawBackRectView(canvas: Canvas) {
        val metrics = textPaint.fontMetrics
        canvas.drawLine(0f, 0f, width.toFloat(), 0f, backgroundLinePaint)
        canvas.drawLine(
            0f,
            height.toFloat(),
            width.toFloat(),
            height.toFloat(),
            backgroundLinePaint
        )
        //基线
        val baseLineY = height * 0.5f + (metrics.bottom - metrics.top) / 2 - metrics.bottom
        //基线到中线的距离
        val topLine = baseLineY + ((metrics.ascent + metrics.descent) / 2 - metrics.descent)
        dashPath.reset()
        dashPath.moveTo(0f, baseLineY)
        dashPath.lineTo(width.toFloat(), baseLineY)
        dashPath.moveTo(0f, topLine)
        dashPath.lineTo(width.toFloat(), topLine)
        canvas.drawPath(dashPath, backgroundDashPaint)
    }

    /**
     * 绘制文字
     */
    private fun drawTextView(canvas: Canvas) {
        contentText?.run {
            val textWidth = textPaint.measureText(this)
            baseLineX = (width - textWidth) * 0.5f
            this.forEachIndexed { index, char ->
                drawItemTextView(index, char, canvas)
            }
        }
    }

    /**
     * 绘制每次字符
     */
    private fun drawItemTextView(index: Int, char: Char, canvas: Canvas) {
        val textWidth = textPaint.measureText(char.toString())
        val metrics = textPaint.fontMetrics
        val baseLineY = height * 0.5f + (metrics.bottom - metrics.top) / 2 - metrics.bottom
        hlPositions?.takeIf { it.contains(index) }?.let { positions ->
            if (connectPositions == positions) {
                connectPositionCoordinate.add(baseLineX + textWidth / 2)
            }
            connectPositions?.takeIf { it.contains(index) && positions.size == contentText?.length }
                ?.run {
                    textPaint.color = connectLineColor
                } ?: kotlin.run {
                textPaint.color = hlTextColor
            }
        } ?: kotlin.run {
            textPaint.color = normalTextColor
        }
        canvas.drawText(char.toString(), baseLineX, baseLineY, textPaint)
        baseLineX += textWidth
    }

    /**
     * 绘制连接线
     */
    private fun drawConnectLineView(canvas: Canvas) {
        hlPositions?.takeIf { it.size == contentText?.length }?.run {
            connectPositionCoordinate.takeIf { it.size > 1 }?.run {
                connectLinePath.reset()
                //基线
                val metrics = textPaint.fontMetrics
                val baseLineY = height * 0.5f + (metrics.bottom - metrics.top) / 2 - metrics.bottom
                //只显示开始和结束两个连接线
                val startX = this[0]
                val endX = this[size - 1]
                connectLinePath.moveTo(startX, baseLineY)
                connectLinePath.lineTo(startX, baseLineY + 10)
                connectLinePath.lineTo(endX, baseLineY + 10)
                connectLinePath.lineTo(endX, baseLineY)
                canvas.drawPath(connectLinePath, connectLinePaint)
            }
        }
    }

    /**
     * 设置文本
     */
    fun setText(text: String) {
        if (TextUtils.isEmpty(text)) {
            return
        }
        contentText = text
        resetTextSize(text)
        invalidate()
    }

    /**
     * 调整文字大小和宽度
     */
    private fun resetTextSize(text: String) {
        val length = text.length
        if (length >= 15) {
            textPaint.textSize = resources.getDimensionPixelSize(R.dimen.small_word_size).toFloat()
            resizeWidth = textPaint.measureText(text).toInt()
            requestLayout()
        } else if (length >= 10) {
            textPaint.textSize = resources.getDimensionPixelSize(R.dimen.middle_word_size).toFloat()
            resizeWidth = textPaint.measureText(text).toInt()
            requestLayout()
        } else if (length > 6) {
            textPaint.textSize = resources.getDimensionPixelSize(R.dimen.large_word_size).toFloat()
            resizeWidth = textPaint.measureText(text).toInt()
            requestLayout()
        }
    }


    /**
     * 设置高亮位置
     */
    fun setHLPositions(positions: List<Int>) {
        hlPositions = positions
        val hasConnectPosition = hasConnectPositions(positions)
        if (hasConnectPosition) {
            connectPositions = hlPositions
        }
        invalidate()
    }

    /**
     * 检测是否有连接点
     */
    private fun hasConnectPositions(positions: List<Int>): Boolean {
        positions.takeIf { it.size > 1 }?.run {
            var lastPositions = 0
            this.forEachIndexed { index, it ->
                if (index != 0 && it > lastPositions + 1) {
                    return true
                }
                lastPositions = it
            }
        }
        return false
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        if (resizeWidth > 0) {
            val measureHeight = MeasureSpec.getSize(heightMeasureSpec)
            val measureWidth = MeasureSpec.getSize(widthMeasureSpec).coerceAtLeast(resizeWidth)
            setMeasuredDimension(measureWidth, measureHeight)
        }
    }

}